<template>
  <m-window-frame
    :title="title"
    style="height: 100%"
    @cancel="handleCancel"
  >
    <div
      class="g-fd-c"
      style="height: 100%"
    >
      <AttrTips
        class="g-flex-0"
        :propertyGroupConfig="attrInfo"
        :type="''"
        background-image="statics/arch/theme/addtitlebg.png"
      ></AttrTips>
      <Step
        v-model="activeKey"
        :steps="steps"
        @stepValueChange="stepValueChange"
      ></Step>
    </div>
    <template v-slot:footer-right>
      <el-button
        size="small"
        :disabled="prevStepDisabled"
        @click="updateStep(-1)"
      >
        {{ "< " + $t(" 上一步") }}
      </el-button>
      <el-button
        size="small"
        :disabled="nextStepDisabled"
        @click="updateStep(1)"
      >
        {{ $t("下一步") + " >" }}
      </el-button>
      <el-button
        type="primary"
        size="small"
        :disabled="okDisabled"
        :loading="saveLoading"
        @click="handleSave"
      >
        {{ $t("完 成") }}
      </el-button>
      <el-button
        size="small"
        @click="handleCancel"
      >
        {{ $t("取 消") }}
      </el-button>
    </template>
  </m-window-frame>
</template>

<script lang="ts" setup>
import MWindowFrame from "@/common/ipcWindow/WindowFrame.vue";
import AttrTips from "@/common/attrTip/AttrTip.vue";
import Step, { type StepItem } from "../createTableWizard/Step.vue";
import { ref, computed, markRaw, reactive, toRaw, watch } from "vue";
import { useRoute } from "vue-router";
import { ipcWindowUtil } from "@/mdesign-lib/mdesign-app.umd.js";
import TreeSelect from "@/modules/model/modals/modelTreeSelect/components/TreeSelect.vue";
import { PropertyDataType } from "@/mdesign-lib/mdesign-app.umd.js";
import DateAndTimeSetting from "../dateAndTimeSettingWindow/DateAndTimeSetting.vue";
import { Params, Result } from "./index";
import { archService } from "@/mdesign-lib/mdesign-app.umd.js";
import ActualProjectMilestoneCreate from "./steps/ActualProjectMilestoneCreate.vue";
import MilestoneStatus from "./steps/MilestoneStatus.vue";
import dayjs from "dayjs";
import isBetween from "dayjs/plugin/isBetween";
import { toMap } from "@/util/common";

dayjs.extend(isBetween);

const result = reactive<Result>({ modelId: "" });
const route = useRoute();
const saveLoading = ref(false);
const title = ref("");
const warningMsr = ref("");
let projectId = "";
let moreBtnCondition = "";
let stepKeys: string[] = [];
let selectedIds: string[] = [];
let stereotype = "";
let defaultName = "";
let minDate = "";
let maxDate = "";
let activeStepKey = "";
let disableStepKey: string[] = [];
let stepParams: Record<string, any> = {};

watch(
  () => route.fullPath,
  () => {
    const routeQuery = route.query as unknown;
    const query = routeQuery as Params;
    title.value = query.title;
    projectId = query.projectId;
    stepKeys = query.stepKeys;
    moreBtnCondition = query.moreBtnCondition || "";
    selectedIds = query.selectedIds || [];
    stereotype = query.stereotype || "";
    defaultName = query.defaultName || "";
    minDate = query.minDate || "";
    maxDate = query.maxDate || "";
    activeStepKey = query.activeStepKey || "";
    disableStepKey = query.disableStepKey || [];
    stepParams = JSON.parse(query.stepParams || "{}") as Record<string, any>;
  },
  { immediate: true }
);

const allSteps: StepItem[] = [
  {
    key: "chooseActualProjectMilestoneNameAndDate",
    name: "选择名称、类型、日期",
    description: "指定实际项目里程碑的名称、类型和日期",
    component: markRaw(ActualProjectMilestoneCreate),
    nextStepDisabled: true,
    params: {
      projectId,
      defaultDate: "",
      stereotype,
      defaultName,
      warningMsr
    }
  },
  {
    key: "chooseActualEnterprisePhase",
    name: "选择实际战略阶段",
    description: "选择一个已存在的战略阶段。",
    component: markRaw(TreeSelect),
    nextStepDisabled: true,
    dataType: "date",
    params: {
      loadMethod: "getPropertyTreeList",
      loadParams: {
        row: {
          dataType: PropertyDataType.INSTANCE,
          moreBtnCondition,
          key: "",
          modelId: moreBtnCondition,
          checkMethod: null,
          nullable: true
        },
        projectId
      },
      multiple: false,
      showNodeLabel: true,
      defaultSelectedId: "",
      defaultRightSelectedIds: selectedIds
    }
  },
  {
    key: "chooseStrategicPhase",
    name: "选择战略阶段",
    description: "选择一个已存在的战略阶段。",
    component: markRaw(TreeSelect),
    nextStepDisabled: true,
    dataType: "date",
    params: {
      loadMethod: "getPropertyTreeList",
      loadParams: {
        row: {
          dataType: PropertyDataType.INSTANCE,
          moreBtnCondition,
          key: "",
          modelId: moreBtnCondition,
          checkMethod: null,
          nullable: true
        },
        projectId
      },
      multiple: false,
      showNodeLabel: true,
      defaultSelectedId: "",
      defaultRightSelectedIds: selectedIds
    }
  },
  {
    key: "chooseResource",
    name: "选择资源",
    description: "选择一个已存在的资源。",
    component: markRaw(TreeSelect),
    nextStepDisabled: true,
    dataType: "date",
    params: {
      loadMethod: "getPropertyTreeList",
      loadParams: {
        row: {
          dataType: PropertyDataType.INSTANCE,
          moreBtnCondition,
          key: "",
          modelId: moreBtnCondition,
          checkMethod: null,
          nullable: true
        },
        projectId
      },
      multiple: false,
      showNodeLabel: true,
      defaultSelectedId: "",
      defaultRightSelectedIds: selectedIds
    }
  },
  {
    key: "chooseActualPerson",
    name: "选择实际人员",
    description: "选择一个已存在的实际人员，设置时间范围，并与图中所选择的实际岗位建立'填充岗位'关联。",
    component: markRaw(TreeSelect),
    nextStepDisabled: true,
    dataType: "date",
    params: {
      loadMethod: "getPropertyTreeList",
      loadParams: {
        row: {
          dataType: PropertyDataType.INSTANCE,
          moreBtnCondition,
          key: "",
          modelId: moreBtnCondition,
          checkMethod: null,
          nullable: true
        },
        projectId
      },
      multiple: false,
      showNodeLabel: true,
      defaultSelectedId: ""
    }
  },
  {
    key: "chooseService",
    name: "选择服务",
    description: "为版本配置分配一个服务，并设置时间。",
    component: markRaw(TreeSelect),
    nextStepDisabled: true,
    dataType: "date",
    params: {
      loadMethod: "getPropertyTreeList",
      loadParams: {
        row: {
          dataType: PropertyDataType.INSTANCE,
          moreBtnCondition,
          key: "",
          modelId: moreBtnCondition,
          checkMethod: null,
          nullable: true
        },
        projectId
      },
      multiple: false,
      showNodeLabel: true,
      defaultSelectedId: ""
    }
  },
  {
    key: "chooseActualProjectMilestoneType",
    name: "选择实际项目里程碑类型",
    description: "选择现有的实际项目里程碑类型。选定的里程碑类型为每个项目进程定义项目线程和状态指示器，用于指定特定里程碑上的项目状态。",
    component: markRaw(TreeSelect),
    nextStepDisabled: true,
    params: {
      loadMethod: "getPropertyTreeList",
      loadParams: {
        row: {
          dataType: PropertyDataType.INSTANCE,
          moreBtnCondition,
          key: "",
          modelId: moreBtnCondition,
          checkMethod: null,
          nullable: true
        },
        projectId
      },
      multiple: false,
      showNodeLabel: true,
      defaultSelectedId: ""
    }
  },
  {
    key: "chooseActualResource",
    name: "选择实际资源",
    description:
      "部署实际负责资源完成所选能力所需的实际资源。 实际负责资源使用负责关系与实际项目里程碑（已部署和不再使用）相关。 实际资源被设置为两个实际项目里程碑的实际资源。 实际资源与使用展示关系的能力相关。",
    component: markRaw(TreeSelect),
    nextStepDisabled: true,
    params: {
      loadMethod: "getPropertyTreeList",
      loadParams: {
        row: {
          dataType: PropertyDataType.INSTANCE,
          moreBtnCondition,
          key: "",
          modelId: moreBtnCondition,
          checkMethod: null,
          nullable: true
        },
        projectId
      },
      multiple: true,
      showNodeLabel: true,
      defaultSelectedId: "",
      defaultRightSelectedIds: selectedIds
    }
  },
  {
    key: "chooseResourceInTypicalTable",
    name: "选择资源",
    description:
      "部署实际负责资源（实际组织、实际人员和实际职位）所需的资源，以完成选定的能力。 实际负责资源使用负责关系与实际项目里程碑（运行中和停止运行）相关。 资源被设置为在运行实际项目里程碑的发布版本和停止运行实际项目里程碑的撤回版本。 资源与使用展示关系的能力相关。",
    component: markRaw(TreeSelect),
    nextStepDisabled: true,
    params: {
      loadMethod: "getPropertyTreeList",
      loadParams: {
        row: {
          dataType: PropertyDataType.INSTANCE,
          moreBtnCondition,
          key: "",
          modelId: moreBtnCondition,
          checkMethod: null,
          nullable: true
        },
        projectId
      },
      multiple: true,
      showNodeLabel: true,
      defaultSelectedId: "",
      defaultRightSelectedIds: selectedIds
    }
  },
  {
    key: "chooseStartDate",
    name: "设置开始时间",
    description: "设置开始时间",
    component: markRaw(DateAndTimeSetting),
    nextStepDisabled: false,
    params: {
      projectId,
      defaultDate: "",
      warningMsr
    }
  },
  {
    key: "chooseEndDate",
    name: "设置结束时间",
    description: "设置结束时间，结束时间需在开始时间之后",
    nextStepDisabled: false,
    component: markRaw(DateAndTimeSetting),
    params: {
      projectId,
      defaultDate: "",
      warningMsr
    }
  },
  {
    key: "chooseDeploymentDate",
    name: "设置部署时间",
    description: "设置部署时间",
    component: markRaw(DateAndTimeSetting),
    nextStepDisabled: false,
    params: {
      projectId,
      defaultDate: "",
      warningMsr
    }
  },
  {
    key: "chooseNoLongerUsedDate",
    name: "设置不再使用时间",
    description: "设置不再使用时间",
    nextStepDisabled: false,
    component: markRaw(DateAndTimeSetting),
    params: {
      projectId,
      defaultDate: "",
      warningMsr
    }
  },
  {
    key: "chooseInServiceDate",
    name: "设置运行时间",
    description: "设置运行时间",
    component: markRaw(DateAndTimeSetting),
    nextStepDisabled: false,
    params: {
      projectId,
      defaultDate: "",
      warningMsr
    }
  },
  {
    key: "chooseOutOfServiceDate",
    name: "设置停止运行时间",
    description: "设置停止运行时间",
    nextStepDisabled: false,
    component: markRaw(DateAndTimeSetting),
    params: {
      projectId,
      defaultDate: "",
      warningMsr
    }
  },
  {
    key: "setMilestoneStatus",
    name: "在特定的里程碑上设置状态",
    description:
      "要在特定的实际项目里程碑处定义项目状态，请选择或创建一个新的项目线并定义其状态指示器。每个项目线由不同的扇区定义，每个状态指示器由项目状态圈中的不同颜色定义。",
    component: markRaw(MilestoneStatus),
    nextStepDisabled: false,
    params: {
      projectId,
      modelIds: []
    }
  }
];
const allStepMap = toMap(allSteps, "key");
const steps = ref<StepItem[]>(
  stepKeys
    .map(key => {
      const data = allStepMap.get(key) as StepItem;
      const params = stepParams[key];
      if (params) {
        data.params = { ...data.params, ...params };
      }
      if (disableStepKey.includes(key)) {
        data.disabled = true;
      }
      return data;
    })
    .filter(Boolean) as StepItem[]
);
const activeKey = ref(activeStepKey || steps.value[0].key);

const activeStep = computed(() => {
  return steps.value.filter(step => step.key === activeKey.value)[0];
});

const canOk = ref(true);

const okDisabled = computed(() => {
  return activeStep.value.nextStepDisabled || !canOk.value || needSetDate.value;
});

const needSetDate = computed(() => {
  let disabled = false;
  const currentstepKeys = steps.value.map(item => item.key);
  if (currentstepKeys.includes("chooseStartDate") && !result.startTime) disabled = true;
  if (currentstepKeys.includes("chooseEndDate") && !result.endTime) disabled = true;
  return disabled;
});

const attrInfo = computed<{ name: string; description: string; icon: string }>(() => {
  return {
    name: activeStep.value.name as string,
    description: activeStep.value.description as string,
    icon: "statics/icons/attrTip/checkbox.svg"
  };
});

const currentStepIndex = computed(() => {
  return steps.value.findIndex(step => step.key === activeKey.value);
});

const prevStepDisabled = computed(() => {
  const prevSteps = steps.value.slice(0, currentStepIndex.value);
  return prevSteps.every(step => step.disabled);
});

const nextStepDisabled = computed(() => {
  const nextSteps = steps.value.slice(currentStepIndex.value + 1, steps.value.length);
  return nextSteps.every(step => step.disabled) || steps.value[currentStepIndex.value].nextStepDisabled;
});

const getStepByKey = (key: string) => {
  return steps.value.find(item => item.key === key);
};

const stepValueChange = (val: any, path: string[]) => {
  const from = path[0];
  const to = path[path.length - 1];
  if (activeStep.value.dataType === "date") {
    result.modelId = val?.length ? val[0] : ("" as typeof result.modelId);
    activeStep.value.nextStepDisabled = true;
    if (!result.modelId) return;
    queryDate(result.modelId)
      .then(({ startDate, endDate }) => {
        steps.value[1].params!.defaultDate = startDate || "";
        steps.value[2].params!.defaultDate = endDate || "";
      })
      .finally(() => {
        activeStep.value.nextStepDisabled = false;
      });
  } else if (from == "chooseStartDate" && to === "date") {
    result.startTime = val;
    const isAfterEndDate = result.endTime ? dayjs(val).isAfter(result.endTime, "milliseconds") : false;
    if (isAfterEndDate) {
      canOk.value = false;
      warningMsr.value = `开始时间早于结束时间 (${result.startTime} - ${result.endTime})`;
    } else {
      canOk.value = true;
      warningMsr.value = "";
    }
  } else if (from == "chooseEndDate" && to === "date") {
    result.endTime = val;
    const isAfterEndDate = result.startTime ? dayjs(result.startTime).isAfter(val, "milliseconds") : false;
    if (isAfterEndDate) {
      canOk.value = false;
      warningMsr.value = `开始时间早于结束时间 (${result.startTime} - ${result.endTime})`;
    } else {
      canOk.value = true;
      warningMsr.value = "";
    }
  } else if (from == "chooseDeploymentDate") {
    if (to === "date") {
      result.startTime = val;
      const startTimeIsBetween = val ? dayjs(val).isBetween(minDate, maxDate, "milliseconds", "[]") : false;
      const endTimeIsBetween = result.endTime ? dayjs(result.endTime).isBetween(minDate, maxDate, "milliseconds", "[]") : true;
      const endIsLateStart = result.endTime ? dayjs(result.endTime).isBetween(result.startTime, maxDate, "milliseconds", "[]") : true;
      if (!startTimeIsBetween) {
        canOk.value = false;
        warningMsr.value = `部署时间需要在实际项目里程碑时间范围内 (${minDate} - ${maxDate})`;
      } else if (!endTimeIsBetween) {
        canOk.value = false;
        warningMsr.value = `不再使用时间需要在实际项目里程碑时间范围内 (${minDate} - ${maxDate})`;
      } else if (!endIsLateStart) {
        canOk.value = false;
        warningMsr.value = `不再使用时间不能早于部署时间 (${result.startTime} - ${maxDate})`;
      } else {
        canOk.value = true;
        warningMsr.value = "";
      }
    } else if (to === "timeLine") {
      result["startTimeLineId"] = val;
    }
  } else if (from == "chooseNoLongerUsedDate") {
    if (to === "date") {
      result.endTime = val;
      const startTimeIsBetween = result.startTime ? dayjs(result.startTime).isBetween(minDate, maxDate, "milliseconds", "[]") : false;
      const endTimeIsBetween = val ? dayjs(val).isBetween(minDate, maxDate, "milliseconds", "[]") : false;
      const endIsLateStart = val ? dayjs(val).isBetween(result.startTime, maxDate, "milliseconds", "[]") : false;

      if (!startTimeIsBetween) {
        canOk.value = false;
        warningMsr.value = `部署时间需要在实际项目里程碑时间范围内 (${minDate} - ${maxDate})`;
      } else if (!endTimeIsBetween) {
        canOk.value = false;
        warningMsr.value = `不再使用时间需要在实际项目里程碑时间范围内 (${minDate} - ${maxDate})`;
      } else if (!endIsLateStart) {
        canOk.value = false;
        warningMsr.value = `不再使用时间不能早于部署时间 (${result.startTime} - ${maxDate})`;
      } else {
        canOk.value = true;
        warningMsr.value = "";
      }
    } else if (to === "timeLine") {
      result["endTimeLineId"] = val;
    }
  } else if (from == "chooseInServiceDate") {
    if (to === "date") {
      result.startTime = val;
      const startTimeIsBetween = val ? dayjs(val).isBetween(minDate, maxDate, "milliseconds", "[]") : false;
      const endTimeIsBetween = result.endTime ? dayjs(result.endTime).isBetween(minDate, maxDate, "milliseconds", "[]") : true;
      const endIsLateStart = result.endTime ? dayjs(result.endTime).isBetween(result.startTime, maxDate, "milliseconds", "[]") : true;
      if (!startTimeIsBetween) {
        canOk.value = false;
        warningMsr.value = `运行时间需要在实际项目里程碑时间范围内 (${minDate} - ${maxDate})`;
      } else if (!endTimeIsBetween) {
        canOk.value = false;
        warningMsr.value = `停止运行时间需要在实际项目里程碑时间范围内 (${minDate} - ${maxDate})`;
      } else if (!endIsLateStart) {
        canOk.value = false;
        warningMsr.value = `停止运行时间不能早于运行时间 (${result.startTime} - ${maxDate})`;
      } else {
        canOk.value = true;
        warningMsr.value = "";
      }
    } else if (to === "timeLine") {
      result["startTimeLineId"] = val;
    }
  } else if (from == "chooseOutOfServiceDate") {
    if (to === "date") {
      result.endTime = val;
      const startTimeIsBetween = result.startTime ? dayjs(result.startTime).isBetween(minDate, maxDate, "milliseconds", "[]") : false;
      const endTimeIsBetween = val ? dayjs(val).isBetween(minDate, maxDate, "milliseconds", "[]") : false;
      const endIsLateStart = val ? dayjs(val).isBetween(result.startTime, maxDate, "milliseconds", "[]") : false;

      if (!startTimeIsBetween) {
        canOk.value = false;
        warningMsr.value = `运行时间需要在实际项目里程碑时间范围内 (${minDate} - ${maxDate})`;
      } else if (!endTimeIsBetween) {
        canOk.value = false;
        warningMsr.value = `停止运行时间需要在实际项目里程碑时间范围内 (${minDate} - ${maxDate})`;
      } else if (!endIsLateStart) {
        canOk.value = false;
        warningMsr.value = `停止运行时间不能早于运行时间 (${result.startTime} - ${maxDate})`;
      } else {
        canOk.value = true;
        warningMsr.value = "";
      }
    } else if (to === "timeLine") {
      result["endTimeLineId"] = val;
    }
  } else if (from === "chooseActualResource" || from === "chooseResourceInTypicalTable") {
    result["modelIds"] = val;
    activeStep.value.nextStepDisabled = !val.length;
    if (result.startTime && result.endTime && !warningMsr.value) {
      canOk.value = true;
    } else {
      canOk.value = false;
    }
  } else if (from === "chooseActualProjectMilestoneNameAndDate") {
    result["properties"] = undefined;
    result[to] = val;
    if (minDate && maxDate) {
      const currentDate = result["date"];
      const between = dayjs(currentDate).isBetween(minDate, maxDate, "milliseconds", "[]");
      if (between) {
        activeStep.value.nextStepDisabled = false;
        warningMsr.value = "";
      } else {
        activeStep.value.nextStepDisabled = true;
        warningMsr.value = `请选择在 {${minDate} - ${maxDate}} 的时间点`;
      }
    }
  } else if (from === "setMilestoneStatus") {
    result["properties"] = val;
  } else if (from === "chooseActualProjectMilestoneType") {
    result.modelId = val?.length ? val[0] : ("" as typeof result.modelId);
    const currentStep = getStepByKey("setMilestoneStatus");
    if (currentStep) {
      currentStep.params!.modelIds = val;
      activeStep.value.nextStepDisabled = !result.modelId;
    }
  }

  if (to === "timeLine") {
    activeStep.value.nextStepDisabled = !val;
    result.timeLineId = val;
  }

  console.log("result", result);
};

const queryDate = async (modelId: string) => {
  const startDate = await archService.queryStartDateByInstance(projectId, modelId);
  const endDate = await archService.queryEndDateByInstance(projectId, modelId);
  return { startDate, endDate };
};

const updateStep = (num: number) => {
  let addNum = num;
  let nextStep = steps.value[currentStepIndex.value + addNum];
  while (nextStep.disabled) {
    addNum += num;
    nextStep = steps.value[currentStepIndex.value + addNum];
  }
  if (nextStep) {
    activeKey.value = nextStep.key;
  }
};

const handleSave = () => {
  saveLoading.value = true;
  ipcWindowUtil.sendWindowChange({ success: true, result: toRaw(result) });
};

function handleCancel() {
  ipcWindowUtil.closeWindow({ success: false, result: toRaw(result) });
}
</script>
